;   This program is free software: you can redistribute it and/or modify
;   it under the terms of the GNU General Public License as published by
;   the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.
;
;   This program is distributed in the hope that it will be useful,
;   but WITHOUT ANY WARRANTY; without even the implied warranty of
;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;   GNU General Public License for more details.
;
;   You should have received a copy of the GNU General Public License
;   along with this program.  If not, see <http://www.gnu.org/licenses/>.

;下行定义你的CPU MODEL
;head 磁头
;track 磁道
;sector 扇区
;Sector of per Track 每磁道扇区数

.286
data segment
CMOS_data db 64 dup (?)
weeks db "SunMonTueWedThuFriSat"
CMOS_length equ 64
CMOS_index_IO equ 070h
CMOS_Read_IO equ 071h

second equ word ptr [bx+00h]
minute equ word ptr [bx+02h]
hour equ word ptr [bx+04h]
week equ byte ptr [bx+06h]
day equ byte ptr [bx+07h]
month equ byte ptr [bx+08h]
year equ byte ptr [bx+09h]
century equ byte ptr [bx+32h]
bootDrive equ byte ptr [bx+0dh]
floppyA equ 01h
floppyB equ 02h
HeadDrive1 equ 80h
HeadDrive2 equ 81h
CMOSstat equ byte ptr [bx+0eh]
FD_TYPE equ byte ptr [bx+010h]
noFD equ 0000b
FD360KB equ 0001b
FD1228KB equ 0010b
FD720KB equ 0011b
FD1474KB equ 0100b
bootpasswordset equ byte ptr [bx+011h]
SYSTEMSTAT equ byte ptr [bx+014h]
NMsize equ word ptr [bx+015h]
XMSsize equ word ptr [bx+017h]
HD1_TYPE equ byte ptr [bx+019h]
HD2_TYPE equ byte ptr [bx+01ah]
TT db "               dump 64 byte CMOS Information:",0dh,0ah,"$"
written db "This program written By boko(2012.5 JiangXi YingTan),All Rights Reserved.",0dh,0ah,"$"
timemsg db "Realtime Clock:"
h db "00"
db ":"
m db "00"
db ":"
s db "00"
db " Date:"
centurys db "  "
y db "  "
db "-"
mon db "  "
db "-"
d db "  "
db " week:"
w db "   ",0dh,0ah,"$"
buff1 db 10 dup (?)
buff2 db 10 dup (?)
buff3 db 30 dup (?)
mem_SIZE_MSG db "Base Memory size:"
Normal_mem_SIZEs db 6 dup (?)
db "Extended Memory size:"
Extend_mem_SIZEs db 14 dup (" ")
db 0dh,0ah,"$"
GEFFFFH db "EMS > 64MB"
noHardDiskDrive db "No Find HardDisk in the system"
HD2MSG db ",HD2 TYPE:"
HDMSG db "HD1 TYPE:"
HDInfo db 71 dup (" ")
db 0dh,0ah,"$"
data ends
stack segment stack
BUF db 256 dup (?)
TOP EQU THIS WORD
stack ends

code segment
assume ds:data,cs:code
assume ss:stack
start:mov ax,data;初始化数据段段基址
      mov ds,ax;将数据段段基址装入DS
      mov es,ax;将数据段段基址装入ES
      mov ax,stack;初始化堆栈段段基址
      mov ss,ax;将堆栈段段基址装入SS
      lea sp,TOP;初始化堆栈段减栈定指针SP
      lea dx,TT
      mov ah,09h
      int 021h
      mov bx,OFFSET CMOS_data;CMOS数据保存位置
      call RDCMOSINFO
      call print_numb_line
      call print__line
      call CMOS_Dump
      call print__line
      lea dx,written
      mov ah,09h
      int 021h
      call clock
      call date
      call weekPROC
      lea dx,timemsg
      mov ah,09h
      int 021h;print CMOS time info
      mov dl,CMOSstat
      call CMOS_STAT
      mov dh,FD_TYPE
      mov dl,SYSTEMSTAT
      call SYSTEM_STAT
      lea di,Normal_mem_SIZEs
      call normalmemory
      lea di,Extend_mem_SIZEs
      call _XMS
      lea dx,mem_SIZE_MSG
      mov ah,09h
      int 21h
      mov al,HD1_TYPE
      lea di,HDInfo
      call SYS_HD_SET
      lea si,HD2MSG
      mov cx,10
      cld
      rep movsb
      mov al,HD2_TYPE
      call SYS_HD_SET
      mov byte ptr[di],0dh
      inc di
      mov byte ptr[di],0ah
      inc di
      mov byte ptr[di],"$"
      lea dx,HDMSG
      mov ah,09h
      int 21h
exit: mov ax,04c00h
      int 021h
;=============================================================
;子程序:读取CMOS基本信息到指定内存
;子程序调用名:RDCMOSINFO
;入口参数:bx
;出口参数:[bx+0]~[bx+64]内存=CMOS基本信息
;-------------------------------------------------------------
RDCMOSINFO proc near
      pusha
      mov cx,CMOS_length;CMOS数据长度
      mov dx,0;地址索引号
again:jmp next1;延迟
next1:jmp next2
next2:mov al,dl
      out CMOS_index_IO,al;地址索引
      jmp next3;延迟
next3:jmp next4
next4:in al,CMOS_Read_IO;读取CMOS信息
      mov [bx],al
      inc bx
      inc dx
      loop again
      popa
      ret
RDCMOSINFO endp
;=============================================================

;=============================================================
;子程序:转换8位HEX码[8bit]为扩展的BCD码[16bit]
;子程序调用名:HEX2BCD8
;入口参数:ds:[si]=需要转换HEX变量存储地址,08bit
;出口参数:ds:[di]=转换后的BCD变量存储地址,16bit
HEX2BCD8 proc near
;-------------------------------------------------------------
      pusha
      mov al,byte ptr [si]
      xor ah,ah
      mov bl,0ah
      div bl
      mov dl,ah
      xor ah,ah
      div bl
      mov dh,al
      mov al,ah
      xor ah,ah
      mov bl,010h
      mul bl
      add ax,dx
      mov [di],byte ptr ah
      inc di
      mov [di],byte ptr al
      popa
      ret
HEX2BCD8 endp
;=============================================================

;=============================================================
;子程序:转换16位HEX码[8bit]为扩展的BCD码[24bit]
;子程序调用名:HEX2BCD16
;入口参数:ds:[si]=需要转换HEX变量存储地址,16bit
;出口参数:ds:[di]=转换后的BCD变量存储地址,24bit
HEX2BCD16 proc near
;-------------------------------------------------------------
      pusha
      mov ax,[si]
      xor dx,dx
      mov bx,0ah
      div bx
      mov bp,dx
      xor dx,dx
      div bx
      mov cl,04h
      shl dx,cl
      and dx,00f0h
      add bp,dx
      xor dx,dx
      div bx
      mov cl,08h
      shl dx,cl
      and dx,0f00h
      add bp,dx
      xor dx,dx
      div bx
      mov cl,0ch
      shl dx,cl
      and dx,0f000h
      add bp,dx
      xor dx,dx
      div bx
      mov ax,bp
      mov [di],byte ptr dl
      inc di
      mov [di],byte ptr ah
      inc di
      mov [di],byte ptr al
      popa
      ret
HEX2BCD16 endp
;=============================================================

;=============================================================
;子程序:转换内存中8位HEX码为扩展的ASCII码
;子程序调用名:HEX2ASCII
;入口参数:ds:[si]=需要转换HEX变量存储地址,8bit
;         ds:[di]=转换后的ASCII变量存储地址,16bit
;出口参数:ds:[di]=转换后的ASCII变量存储地址,16bit
HEX2ASCII proc near
;-------------------------------------------------------------
      pusha
      MOV DL,byte ptr[si]
      MOV CL,4
      SHR DL,CL;右移4位获得高4位
      ADD DL,030H;0～9加30H,A~F加37H
      CMP DL,'9';将双分支转化为单分支
      JBE NEXT1
      ADD DL,7
NEXT1:MOV byte ptr[di],DL
      INC DI
      MOV DL,byte ptr[si]
      AND DL,0FH;高4位清0获得低4位
      ADD DL,30H
      CMP DL,'9'
      JBE NEXT2
      ADD DL,7
NEXT2:MOV byte ptr[di],DL
      popa
      ret
HEX2ASCII endp
;=============================================================

;=============================================================
;子程序:转换寄存器中的8位HEX码为扩展的ASCII码
;子程序调用名:RHEX2ASCII
;入口参数:dl
;出口参数:ds:[di]=转换后的ASCII变量存储地址,16bit
RHEX2ASCII proc near
;-------------------------------------------------------------
      pusha
      MOV DH,DL
      MOV CL,4
      SHR DL,CL;右移4位获得高4位
      ADD DL,030H;0～9加30H,A~F加37H
      CMP DL,'9';将双分支转化为单分支
      JBE NEXT1
      ADD DL,7
NEXT1:MOV byte ptr[di],DL
      INC DI
      MOV DL,DH
      AND DL,0FH;高4位清0获得低4位
      ADD DL,30H
      CMP DL,'9'
      JBE NEXT2
      ADD DL,7
NEXT2:MOV byte ptr[di],DL
      popa
      ret
RHEX2ASCII endp
;=============================================================

;=============================================================
;子程序:将指定内存的ASCII数字修正成输出格式
;子程序调用名:FORMATNumString
;入口参数:CX=输入数字字符串长度 dl=对齐方式 0f0H=左对齐 0fh=右对齐 [SI]=数字字符串源地址,[di]=数字字符串目的地址
;出口参数:[di]中的字符串修正成为 需要的输出格式 CX=修正后的有效数字串长度
FORMATNumString proc near
;-------------------------------------------------------------
                push ax
    	push bx
		push dx
		push di
		push si
		push bp
                mov dh,"0"
		cmp dh,[si]
		jne FIXALL
		push si
		push di
		push cx
		mov al," "
		cld
		rep stosb
		pop cx
		pop di
		pop si
		push cx
                mov ax,si
		xchg si,di
                push ax
		mov al,"0"
		cld
		repz scasb
                pop ax
		pop cx
                push di
		sub di,ax
		mov ax,di
		pop di
                cmp dl,0f0h
		je left
		add si,ax
		dec si
	   left:sub cx,ax
		xchg si,di
                dec si
		inc cx
		push cx
		cld
		rep movsb
 		jmp FIXOK
         FIXALL:push cx
	        cld
	        rep movsb
          FIXOK:pop cx
	        pop bp
	        pop si
		pop di
		pop dx
		pop bx
		pop ax
		ret
FORMATNumString endp
;=============================================================

; shows text after the call to this function.
show proc near
    again:pop si
          lodsb;获取字符,get character
          push si;将字符串当前字符压入堆栈,stack up potential return address
	  mov ah,0Eh;显示字符,show character
          int 010h;调用"电传打字机"模式,via "TTY" mode
          cmp al,'.';字符串结束?end of string?
          jne again;还未结束until done
          ret
show endp

; shows B text after the call to this function.
showB proc near
    again:pop si
          lodsb;获取字符,get character
          push si;将字符串当前字符压入堆栈,stack up potential return address
	  mov ah,0Eh;显示字符,show character
          int 010h;调用"电传打字机"模式,via "TTY" mode
          cmp al,0ah;字符串结束?end of string?
          jne again;还未结束until done
          ret
showB endp

clock proc near
      pusha
      mov dx,hour
      lea di,h
      call RHEX2ASCII
      mov dx,minute
      lea di,m
      call RHEX2ASCII
      mov dx,second
      lea di,s
      call RHEX2ASCII
      popa
      ret
clock endp

 date proc near
      pusha
      mov dl,year
      lea di,y
      call RHEX2ASCII
      mov dl,month
      lea di,mon
      call RHEX2ASCII
      mov dl,day
      lea di,d
      call RHEX2ASCII
      mov dl,century
      lea di,centurys
      call RHEX2ASCII
      popa
      ret
 date endp

weekPROC proc near
      pusha
      xor ah,ah
      mov al,week
      dec ax
      mov dl,3
      mul dl
      xor ah,ah
      lea si,weeks
      add si,ax
      lea di,w
      mov cx,3
      cld
      rep movsb
      popa
      ret
weekPROC endp

CMOS_STAT proc near
          pusha
          push es
	  push ds
	  push cs
	  pop ax
	  mov ds,ax
	  mov es,ax
	  call showB
	  db "Diagnostic status:",0dh,0ah
     CTER:test dl,0100b
          jne CMOS_Time_Err
	  call show
	          db "CMOS time:---------------------pass."
	  jmp CHER
CMOS_Time_Err:
	  call show
	  db 0dh,0ah,"CMOS time CRC:----------------Error."
     CHER:test dl,01000b
	  jne CMOS_HD_Err
          call show
	  db 0dh,0ah,"BIOS POST HD check:------------pass."
	  jmp CMER
CMOS_HD_Err:
	  call show
	  db 0dh,0ah,"System boot HD check:---------Error."	  
     CMER:test dl,010000b
	  jne CMOS_MEMSIZE_Err
          call show
	  db 0dh,0ah,"Base memory size:--------------pass."
	  jmp CSER
CMOS_MEMSIZE_Err:
	  call show
	  db 0dh,0ah,"Base memory size:-------------Error."
     CSER:test dl,0100000b
	  jne CMOS_SYSSET_Err
          call show
	  db 0dh,0ah,"CMOS SYSTEM SET:---------------pass."
	  jmp CCRCER
CMOS_SYSSET_Err:
	  call show
	  db 0dh,0ah,"CMOS SET:---------------------Error."
   CCRCER:test dl,01000000b
	  jne CMOS_CRC_Err
          call show
	  db 0dh,0ah,"CMOS CRC:----------------------pass."
	  jmp BTLOW
CMOS_CRC_Err:
	  call show
	  db 0dh,0ah,"CMOS CRC Check:---------------Error."	  
    BTLOW:test dl,010000000b
	  jne CMOS_BTPOWLOW_Err
	  call show
	  db 0dh,0ah,"CMOS battery power:------------pass."
          jmp CKnoError
CMOS_BTPOWLOW_Err:
	  call show
	  db 0dh,0ah,"CMOS battery power has been low."
          jmp RTMP1
CKnoError:call showB
	  db 0dh,0ah
          cmp dl,0
	  jne RTMP1
          call showB
	  db "CMOS Check no error",0dh,0ah
    RTMP1:pop ds
          pop es
          popa
	  ret
CMOS_STAT endp

SYSTEM_STAT proc near
            pusha
            push es
            push ds
            push cs
            pop ax
            mov ds,ax
            mov es,ax
  Tfloppy:test dl,01b
          je Nofloppy
          shr dh,04
	  and dh,0fh
	  cmp dh,FD1474KB
	  je FD1474KBs
	  cmp dh,FD720KB
	  je FD720KBs
          cmp dh,FD1228KB
	  je FD1228KBs
	  cmp dh,FD360KB
	  je FD360KBs
	  cmp dh,noFD
	  jne Nofloppy
	  call showB
	  db "Other Flooppy Drive",0dh,0ah
	  jmp TFPU
FD1474KBs:call showB
          db "1.44MB 3` Floppy Drive",0dh,0ah
          jmp TFPU
FD720KBs:call showB
          db "720KB 3` Floppy Drive",0dh,0ah
          jmp TFPU
FD1228KBs:call showB
          db "1.2MB 5` Floppy Drive",0dh,0ah
          jmp TFPU
FD360KBs:call showB
          db "360KB 3` Floppy Drive",0dh,0ah
          jmp TFPU
Nofloppy:call showB
	  db "No floppy Instead.",0dh,0ah
TFPU:test dl,010b
          je NoFPU
          call showB
	  db "FPU Has been enable",0dh,0ah
	  jmp VideoMode
NoFPU:call showB
      db "FPU disable,not find FPU",0dh,0ah
VideoMode:test dl,0100000b
	  jne CGA80_DMA
	  test dl, 010000b
	  jne CGA40
  VGA_EGA:call showB
          db "Video Mode:VGA/EGA(0)",0dh,0ah
          jmp RTMP2
    CGA40:call showB
          db "Video Mode:CGA40(1)",0dh,0ah
	  jmp RTMP2
CGA80_DMA:test dl, 010000b
	  jne DM
    CGA80:call showB
          db "Video Mode:CGA80(2)",0dh,0ah
	  jmp RTMP2
       DM:call showB
          db "Video Mode:MGA(3)",0dh,0ah
      RTMP2:pop ds
            pop es
            popa
	    ret
SYSTEM_STAT endp

normalmemory proc near
             push ax
	     push bx
	     push dx
             push si
	     push bp
	     push di
	     mov ax,NMsize
	     mov word ptr buff1,ax
	     lea si,buff1
	     lea di,buff2
             call HEX2BCD16
             xchg si,di
             mov cx,3
       AGAIN:call HEX2ASCII
	     inc si
	     add di,2
             loop AGAIN
	     mov cx,6
	     mov dl,0f0h
	     lea si,buff1
	     lea di,buff2
	     call FORMATNumString
             add di,cx
	     mov byte ptr [di],"K"
	     inc di
	     mov byte ptr [di],"B"
	     inc di
	     mov byte ptr [di],","
	     pop di
	     add cx,3
	     push cx
	     lea si,buff2
	     cld
	     rep movsb
	     pop cx
             pop bp
	     pop si
	     pop dx
	     pop bx
	     pop ax
	     ret
normalmemory endp

_XMS proc near
             push ax
	     push bx
	     push dx
             push si
	     push bp
	     push di
	     mov ax,XMSsize
	     cmp ax,0ffffh
	     jne next
	     lea si,GEFFFFH
	     pop di
	     mov cx,10
             push cx
	     cld
	     rep movsb
	     jmp RTPM
        next:mov word ptr buff1,ax
	     lea si,buff1
	     lea di,buff2
             call HEX2BCD16
             xchg si,di
             mov cx,3
       AGAIN:call HEX2ASCII
	     inc si
	     add di,2
             loop AGAIN
	     mov cx,6
	     mov dl,0f0h
	     lea si,buff1
	     lea di,buff2
	     call FORMATNumString
             add di,cx
	     mov byte ptr [di],"K"
	     inc di
	     mov byte ptr [di],"B"
	     inc di
	     mov byte ptr [di],0dh
	     inc di
	     mov byte ptr [di],0ah
	     inc di
	     mov byte ptr [di],"$"
	     pop di
	     add cx,5
	     push cx
	     lea si,buff2
	     cld
	     rep movsb
        RTPM:pop cx
             pop bp
	     pop si
	     pop dx
	     pop bx
	     pop ax
     ret
_XMS endp

;mov al,HD1_TYPE
SYS_HD_SET proc near
           cmp al,0
	   je noHDinstall
	   push di
	   mov byte ptr buff1,al
	   lea si,buff1
	   lea di,buff2
	   mov byte ptr [di],"0"
	   inc di
	   call HEX2ASCII
	   lea di,buff2
	   add di,3
	   mov byte ptr [di],"h"
	   inc di
	   pop di
	   lea si,buff2
	   mov cx,4
	   cld
	   rep movsb
	   jmp RTMP
noHDinstall:lea si,noHardDiskDrive
            mov cx,30
	    cld
	    rep movsb
      RTMP:ret
SYS_HD_SET endp

CMOSINFOPRINT proc near
              call print_numb_line

	      ret
CMOSINFOPRINT endp

print_numb_line proc near
                pusha
		mov cx,8
         again1:mov al," "
		mov ah,0Eh
                int 010h
		loop again1
		mov dl,00
		mov cx,10h
		lea di,buff1
         again2:call RHEX2ASCII
		add di,2
		inc dl
		loop again2
		lea si,buff1
                mov cx,10h
		mov ah,0eh
	 again3:cld
		lodsb
		int 010h
		lodsb
		int 010h
		mov al," "
		int 10h
		loop again3
		mov al,0dh
		int 10h
		mov al,0ah
		int 10h
		popa
		ret
print_numb_line endp

print__line proc near
            pusha
	    mov cx,03ah
	    mov al,"-"
      again:mov ah,0eh
	    int 10h
	    loop again
            mov al,0dh
            int 10h
            mov al,0ah
            int 10h
	    popa
	    ret
print__line endp

CMOS_Dump proc near
                pusha
		lea si,CMOS_data
		mov cx,4
                mov dh,00
	 again4:push cx
	        xchg dh,dl
		lea di,buff1
                call RHEX2ASCII
		xchg dh,dl
		add dh,10h
		lea di,buff1
		mov al,byte ptr[di]
		mov ah,0eh
		int 10h
		inc di
		mov al,byte ptr[di]
		mov ah,0eh
		int 10h
		mov al,"h"
		mov ah,0eh
		int 10h
		mov cx,5
         again1:mov al," "
		mov ah,0Eh
                int 010h
		loop again1
		mov dl,00
		mov cx,10h
		lea di,buff1
         again2:call HEX2ASCII
		add di,2
		inc si
		inc dl
		loop again2
		push si
		lea si,buff1
                mov cx,10h
		mov ah,0eh
	 again3:cld
		lodsb
		int 010h
		lodsb
		int 010h
		mov al," "
		int 10h
		loop again3
		pop si
		mov al,0dh
		int 10h
		mov al,0ah
		int 10h
		pop cx
		loop again4
		popa
	        ret
CMOS_Dump endp

code ends
     end start
